#include "thumbitem.h"

#include "AEE.h"
#include "AEEImageWidget.h"
#include "AEEPropContainer.h"
#include "dfon_comdef.h"
#include "node.h"

typedef struct ThumbItem
{
	IPropContainer *propContainer;
	IWidget *imageWidget;
	IModel *model;
	ModelListener mdlListener;
	HandlerDesc hdesc;
	IImage *busyImage;
	IImage *brokenImage;
} ThumbItem ;

static void OnModelEvent(void *userData, ModelEvent *event)
{
	AEERect r;
	ThumbItem *me = userData;

	if(event->evCode == EVT_MDL_VALUE)
	{
		NodeFile *node = IVALUEMODEL_GetValue((IValueModel*)event->pModel, NULL);
		if(node && node->base.type == NodeTypeFile)
		{
			switch(node->loadStage)
			{
			case ImageLoadPending:
			case ImageLoadInProgress:
				IWIDGET_SetImage(me->imageWidget, me->busyImage);
				break;
			case ImageLoadFailed:
				IWIDGET_SetImage(me->imageWidget, me->brokenImage);
				break;
			case ImageLoadSuccess:
				IWIDGET_GetClientRect(me->imageWidget, &r);
				if(r.dx == 0 || r.dy == 0)
					break;
				IWIDGET_SetImage(me->imageWidget, NULL);
				if(node->imageInfo.cx > r.dx || node->imageInfo.cy > r.dy)
				{
					double xRatio = node->imageInfo.cx / (double)r.dx;
					double yRatio = node->imageInfo.cy / (double)r.dy;
					double ratio = MAX(yRatio, xRatio);
					IImage_SetParm(node->image, IPARM_SCALE, (int)(node->imageInfo.cx/ratio), 
						(int)(node->imageInfo.cy/ratio));
				}
				else {
					IImage_SetParm(node->image, IPARM_SCALE, (int)(node->imageInfo.cx), 
						(int)(node->imageInfo.cy));
				}
				IWIDGET_SetImage(me->imageWidget, node->image);
				break;
			}
		}
	}
}

static void ThumbItem_Free(void *data)
{
	ThumbItem *me = data;
	LISTENER_Cancel(&me->mdlListener);
	RELEASEIF(me->brokenImage);
	RELEASEIF(me->busyImage);
	RELEASEIF(me->model);
	RELEASEIF(me->imageWidget);
	HANDLERDESC_Free(&me->hdesc);
	FREEIF(data);
}

static void ThumbItem_HandleEvent(void *data, AEEEvent evt, uint16 wParam, uint32 dwParam)
{
	ThumbItem *me = data;

	if(evt == EVT_WDG_SETPROPERTY)
	{
		IWIDGET_HandleEvent(me->imageWidget, evt, wParam, dwParam);
	}

	HANDLERDESC_Call(&me->hdesc, evt, wParam, dwParam);
}

int ThumbItem_New(IWidget** ppo, IShell *shell)
{
	WidgetProp prop = {1, TRUE};
	int retval = SUCCESS;
	ThumbItem *me = MALLOCREC(ThumbItem);
	IWidget *containerWidget = NULL;

	if(!me)
		return ENOMEMORY;

	ISHELL_CreateInstance(shell, AEECLSID_PROPCONTAINER, (void**)&me->propContainer);
	ISHELL_CreateInstance(shell, AEECLSID_VALUEMODEL, (void**)&me->model);
	ISHELL_CreateInstance(shell, AEECLSID_IMAGEWIDGET, (void**)&me->imageWidget);
	IPROPCONTAINER_QueryInterface(me->propContainer, AEEIID_WIDGET, (void**)&containerWidget);
	if(!me->model || !me->propContainer || !me->imageWidget || !containerWidget)
	{
		retval = ENOMEMORY;
		goto cleanup;
	}

	me->brokenImage = ISHELL_LoadBusyImage(shell);
	me->busyImage = ISHELL_LoadBusyImage(shell);
	IWIDGET_SetFlags(me->imageWidget, IDF_ALIGN_CENTER|IDF_ALIGN_MIDDLE);
	IWIDGET_SetModel(containerWidget, me->model);
	HANDLERDESC_Init(&me->hdesc, ThumbItem_HandleEvent, me, ThumbItem_Free);
	IWIDGET_SetHandler(containerWidget, &me->hdesc);
	IMODEL_AddListenerEx(me->model, &me->mdlListener, OnModelEvent, me);
	IPROPCONTAINER_Insert(me->propContainer, me->imageWidget, WIDGET_ZNORMAL, &prop);

	*ppo = containerWidget;

cleanup:
	if(retval != SUCCESS)
		ThumbItem_Free(me);
	RELEASEIF(containerWidget);
	return retval;
}